﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

// To allow extension methods when targeting .Net 2.0.
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
         | AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute { }
}

namespace InfoPathHelpers.Internal
{
    public static class ImageExtensions
    {
        public static Image ReduceImageSize(this Image inputImage, int maxWidth, int maxHeight)
        {
            int InputWidth = inputImage.Width;
            int InputHeight = inputImage.Height;

            if (maxWidth == 0)
            {
                maxWidth = InputWidth;
            }

            if (maxHeight == 0)
            {
                maxHeight = InputHeight;
            }

            // To preserve the aspect ratio
            float RatioX = (float)maxWidth / InputWidth;
            float RatioY = (float)maxHeight / InputHeight;
            float Ratio = Math.Min(RatioX, RatioY);


            Image OutputImage;

            if (Ratio <= 1)
            {
                // New width and height based on aspect ratio
                int OutputWidth = (int)(InputWidth * Ratio);
                int OutputHeight = (int)(InputHeight * Ratio);

                // Convert other formats (including CMYK) to RGB.
                OutputImage = new Bitmap(OutputWidth, OutputHeight, PixelFormat.Format24bppRgb);

                // Draws the image in the specified size with quality mode set to HighQuality
                using (Graphics Graphics = Graphics.FromImage(OutputImage))
                {
                    Graphics.CompositingQuality = CompositingQuality.HighQuality;
                    Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    Graphics.SmoothingMode = SmoothingMode.HighQuality;
                    Graphics.DrawImage(inputImage, 0, 0, OutputWidth, OutputHeight);
                }
            }
            else
            {
                OutputImage = inputImage;
            }

            return OutputImage;
        }

        public static Image ChangeFormat(this Image inputImage, ImageFormat newFormat)
        {
            Image OutputImage;

            if (inputImage.RawFormat.Equals(newFormat))
            {
                OutputImage = inputImage;
            }
            else
            {
                // Save the input image into a stream using new image format.
                var Stream = new System.IO.MemoryStream();
                inputImage.Save(Stream, newFormat);

                // Create an image from the stream.
                Stream.Seek(0, System.IO.SeekOrigin.Begin);
                OutputImage = Image.FromStream(Stream);
            }

            return OutputImage;
        }

        public static Image ReduceQuality(this Image inputImage, int quality)
        {
            if(quality < 1 || quality > 100)
            {
                throw new ArgumentException("quality must be betwwen 1 and 100.", "quality");
            }

            Image OutputImage;

            if(quality != 100)
            {

                // Get an ImageCodecInfo object that represents the JPEG codec.
                ImageCodecInfo JpegCodec = GetEncoderInfo(ImageFormat.Jpeg);

                // Create an encoder with the Jpeg codec.
                System.Drawing.Imaging.Encoder QualityEncoder =
                    System.Drawing.Imaging.Encoder.Quality;

                // Create the encoder parameters with specified quality level.
                EncoderParameter QualityParameter = new EncoderParameter(QualityEncoder, quality);
                EncoderParameters EncoderParameters = new EncoderParameters(1);
                EncoderParameters.Param[0] = QualityParameter;

                // Save the input image into a stream using the encoder and parameters.
                var Stream = new System.IO.MemoryStream();
                inputImage.Save(Stream, JpegCodec, EncoderParameters);

                // Create an image from the stream.
                Stream.Seek(0, System.IO.SeekOrigin.Begin);
                OutputImage =  Image.FromStream(Stream);
            }
            else
            {
                OutputImage =  inputImage;
            }

            return OutputImage;
        }

        public static string GetName(this ImageFormat imageFormat)
        {
            string FormatName = string.Empty;

            if (ImageFormat.Bmp.Equals(imageFormat))
            {
                FormatName = "Bmp";
            }
            else if (ImageFormat.Emf.Equals(imageFormat))
            {
                FormatName = "Emf";
            }
            else if (ImageFormat.Exif.Equals(imageFormat))
            {
                FormatName = "Exif";
            }
            else if (ImageFormat.Gif.Equals(imageFormat))
            {
                FormatName = "Gif";
            }
            else if (ImageFormat.Icon.Equals(imageFormat))
            {
                FormatName = "Icon";
            }
            else if (ImageFormat.Jpeg.Equals(imageFormat))
            {
                FormatName = "Jpeg";
            }
            else if (ImageFormat.MemoryBmp.Equals(imageFormat))
            {
                FormatName = "MemoryBmp";
            }
            else if (ImageFormat.Png.Equals(imageFormat))
            {
                FormatName = "Png";
            }
            else if (ImageFormat.Tiff.Equals(imageFormat))
            {
                FormatName = "Tiff";
            }
            else if (ImageFormat.Wmf.Equals(imageFormat))
            {
                FormatName = "Wmf";
            }

            return FormatName;
        }

        private static ImageCodecInfo GetEncoderInfo(ImageFormat format)
        {
            return Array.Find(ImageCodecInfo.GetImageDecoders(), delegate(ImageCodecInfo Codec)
            {
                return Codec.FormatID == format.Guid;
            });
        }
    }
}
